import os
import random
import string
import subprocess
from django.shortcuts import render
from django.shortcuts import render,get_object_or_404, redirect
from admin.decorators import superuser_only
from django.contrib.auth.models import User
from appstore.models import AppStore
from appstore.forms import AppStoreForm
from computes.models import Compute
from instances import utils
from instances.models import Instance
from libvirtmgr.create import wvmCreate
from projsettings.models import AppSettings
from cloudlte.settings import DEBUGTAG
from libvirt import libvirtError
from libvirtmgr import util
from django.contrib import messages
from projsettings.settings import app_settings
from django.utils.translation import gettext_noop as _
from logs.views import addlogmsg
# Create your views here.

def appstorepage_index(request):
    instances = None

    computes = (
        Compute.objects.all()
        .order_by("name")
        .prefetch_related("instance_set")
        .prefetch_related("instance_set__userinstance_set")
    )
    for compute in computes:
        utils.refr(compute)

    if request.user.is_superuser or request.user.has_perm("instances.view_instances"):
        instances = Instance.objects.all().prefetch_related("userinstance_set")
    else:
        instances = Instance.objects.filter(
            userinstance__user=request.user
        ).prefetch_related("userinstance_set")
    
    userinfo=get_object_or_404(User, pk=request.user.pk)
    app_data = AppStore.objects.all()
    image_path=AppSettings.objects.get(key='QCOW_FILE_PATH').value
    filelist=os.listdir(image_path)
    
    return render(
        request,
        'appstore_index.html',
        locals()
    )


@superuser_only
def appstore_list(request):
    app_data = AppStore.objects.all()
    appstore_form = AppStoreForm()
    if appstore_form.is_valid():
        appstore_form.save()
        return redirect("appstore:appstore_list")
    
    return render(
        request,
        "appstore_data.html",
        locals()
    )


def get_qemu_img_virtual_size(image_path):
    # 调用qemu-img命令获取虚拟机镜像的信息
    cmd = 'qemu-img info {}'.format(image_path)
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    # 检查命令是否成功执行
    if result.returncode != 0:
        print('Error executing command: {}'.format(cmd))
        print('Error output:', result.stderr.decode())
        return None

    # 从命令输出中提取虚拟大小的值
    output = result.stdout.decode()
    virtual_size_line = None
    for line in output.split('\n'):
        if 'virtual size' in line:
            virtual_size_line = line
            break

    # 提取虚拟大小的值并转换为整数（以GB为单位）
    virtual_size = int(virtual_size_line.split(':')[1].strip().split()[0])
    virtual_size_gb = virtual_size / (1024 * 1024)  # convert to GB
    return virtual_size_gb

@superuser_only
def appstore_createdata(request):
    appstore_form = AppStoreForm(request.POST or None, request.FILES or None)
    if appstore_form.is_valid():
        # volimg_value = app_settings.QCOW_FILE_PATH+'/'+appstore_form.cleaned_data['volimg']
        # if 'qcow' in os.path.splitext(volimg_value)[1]:
        #     total_size = round(get_qemu_img_virtual_size(volimg_value),2)
        # else:
        #     total_size = 0
        # # 获取镜像的总大小（以字节为单位）
        # appstore_form.fields['sysdisk'].value=total_size
        # print(DEBUGTAG,appstore_form.cleaned_data)
        appstore_form.save()
        return redirect("appstore:appstore_list")
    
    return render(
        request,
        "appstore_data.html",
        locals()
    )

@superuser_only
def appstore_delete(request,pk):
    appstore = get_object_or_404(AppStore,pk=pk)
    if request.method == "POST":
        appstore.delete()
        return redirect("appstore:appstore_list")

    return render(
        request,
        "admin/confirm_delete.html",
        {"object": appstore},
    )


def generate_random_chars(n=4):
    """
    生成一个字典，其中每个键对应一个随机字符。
    
    参数:
        n (int): 生成的随机字符数量。
    """
    chars=''
    for i in range(n):
        char = random.choice(string.ascii_letters + string.digits)  # 从所有大小写字母和数字中选择一个字符
        chars = chars+char
    return chars



@superuser_only
def create_appstore_instance(request):
    sub_info=request.POST.get('subinfo')
    compute_id=sub_info.split(',')[0]
    appflavor_id=sub_info.split(',')[1]
    
    conn = None
    volume_list = list()
    meta_prealloc = False
    compute = get_object_or_404(Compute, pk=compute_id)
    appstore = get_object_or_404(AppStore, pk=appflavor_id)
    default_instance_storage = app_settings.INSTANCE_STORAGE
    default_disk_owner_uid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_UID)
    default_disk_owner_gid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_GID)
    default_bus = app_settings.INSTANCE_VOLUME_DEFAULT_BUS
    default_scsi_disk_model = app_settings.INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER
    default_discard = app_settings.INSTANCE_VOLUME_DEFAULT_DISCARD
    default_zeroes = app_settings.INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES
    default_io = app_settings.INSTANCE_VOLUME_DEFAULT_IO
    default_arch = app_settings.INSTANCE_ARCH_DEFAULT_TYPE
    default_machine = app_settings.INSTANCE_MACHINE_DEFAULT_TYPE
    
    try:
        conn = wvmCreate(
            compute.hostname,
            compute.login,
            compute.password,
            compute.type
        )
        
        vm_name=(appstore.name+'_' + generate_random_chars(4)).replace(' ','')
        
        try:
            templ_path = conn.get_volume_path(appstore.volimg)
            dest_vol = conn.get_volume_path(
                vm_name + ".img", default_instance_storage
            )
            if dest_vol:
                raise libvirtError(
                    _(
                        "Image has already exist. Please check volumes or change instance name"
                    )
                )
            else:
                clone_path = conn.clone_from_template(
                    vm_name,
                    templ_path,
                    default_instance_storage,
                    meta_prealloc,
                    default_disk_owner_uid,
                    default_disk_owner_gid,
                )
                volume = dict()
                volume["path"] = clone_path
                volume["type"] = conn.get_volume_format_type(clone_path)
                volume["device"] = "disk"
                volume["cache_mode"] = "directsync"
                volume["bus"] = default_bus
                if volume["bus"] == "scsi":
                    volume["scsi_model"] = default_scsi_disk_model
                volume["discard_mode"] = default_discard
                volume["detect_zeroes_mode"] = default_zeroes
                volume["io_mode"] = default_io
                volume_list.append(volume)
        except Exception as Error:
            messages.error(request, Error)
        
        uuid = util.randomUUID()
        
        try:
            conn.create_instance(
                name=vm_name,
                memory=appstore.ram,
                vcpu=appstore.vcpu,
                vcpu_mode='host-model',
                uuid=uuid,
                arch=default_arch,
                machine=default_machine,
                firmware={},
                volumes=volume_list,
                networks='default',
                virtio=True,
                listener_addr='0.0.0.0',
                nwfilter='',
                graphics='vnc',
                video='vga',
                console_pass='',
                mac=utils.get_random_mac_address(),
                qemu_ga=True,
                add_cdrom='sata',
                add_input='default',
            )
            create_instance = Instance(
                compute_id=compute_id, name=vm_name, uuid=uuid
            )
            create_instance.save()
            msg = _("Instance is created")
            messages.success(request, msg)
            addlogmsg(
                request.user.username,
                create_instance.compute.name,
                create_instance.name,
                msg,
            )
            return redirect("appstore:appstore_index")
        except libvirtError as lib_err:
            messages.error(request, lib_err)
        conn.close()
        
    except libvirtError as lib_err:
        messages.error(request, lib_err)